#ifndef EVENTQUEUE_H
#define EVENTQUEUE_H

#include "main.h"
#include "SweepLine.h"
#include "structures.h"

class EventQueue {
    int      ne;               //vsetkych eventov
    int      ix;               //index
    Event*   Edata;            //pole eventov
    Event**  Eq;               //zotriedeny list pointrov na pole
public:
	//vytvori novu radu eventov z vektoru segmentov
	EventQueue::EventQueue(vector<SLseg*> seg);
    ~EventQueue(void) { delete Eq; delete Edata;}
	//vrati dalsi neobsluzeny event v poradi
    Event* next();				
	//prida novy event, vracia uspesnost
	bool add(Point * p, SLseg * upper, SLseg * lower);
};

//komparator na eventy pre qsort
int E_compare( const void* v1, const void* v2 ) 
{
    Event**    e1 = (Event**)v1;
    Event**    e2 = (Event**)v2;
    return eventorder(*e1,*e2);
}
EventQueue::EventQueue(vector<SLseg*> P)
{
    ix = 0;
	ne = 2 * P.size();          //2 vrcholy na segment

	Edata	= (Event*)   new Event[ne];
    Eq		= (Event**)  new Event * [ne];
	//init pointrov
    for (int i=0; i < ne; i++)         
        Eq[i] = &Edata[i];

    //init eventov
    for (int i=0; i < (int)P.size(); i++) 
	{      
        Eq[2*i]->edge = i;
        Eq[2*i+1]->edge = i;
		//prva udalost
		Eq[2*i]->eV   = &(P.at(i)->lP);
		Eq[2*i]->another_vertex = &(P.at(i)->rP);
		//druha udalost
		Eq[2*i+1]->eV = &(P.at(i)->rP);
		Eq[2*i+1]->another_vertex = &(P.at(i)->lP);
		//typ
        if (xyorder(&(P.at(i)->lP), &(P.at(i)->rP)) < 0) 
		{ 
            Eq[2*i]->type = LEFT;
            Eq[2*i+1]->type = RIGHT;
        }
        else 
		{
            Eq[2*i]->type = RIGHT;
            Eq[2*i+1]->type = LEFT;
        }
		//nove a neobsluzene
		Eq[2*i]->served = Eq[2*i+1]->served = false;
    }

    //utried
	qsort( Eq, ne, sizeof(Event*), E_compare );

#ifdef DEBUG
	for (int i=0; i < (int)P.size(); i++) 
	{
		Eq[2*i]->eV->Print("");
		Eq[2*i+1]->eV->Print("");
	}
#endif
}
Event* EventQueue::next()
{
	//ak uz sme na konci, vrat 0
    if (ix >= ne) return (Event*)0;
	//prejdi pole a najdi prvu eventu na obsluzenie 
	while (Eq[ix]->served) 
	{
		ix++;
		if (ix >= ne) return (Event*)0;
	}
	Eq[ix]->served = true;
	//vrat nasledujucu event
    return Eq[ix++];
}
bool EventQueue::add(Point * p, SLseg * upper, SLseg * lower)
{
	//overit ci tam este nie je 
	for (int i = 0; i < ne; i++)
	{
		if ((Eq[i]->eV->x == p->x)&&(Eq[i]->eV->y == p->y)&&(Eq[i]->type == INTERSECTION)) return false;
	}

	ne++;
	//nova pamat
	Eq = (Event**) realloc (Eq, ne*sizeof(Event));
	if (Eq == NULL) { cout << "Error (re)allocating memory" << endl; exit (1); }
    //pridaj event
	Eq[ne-1] = new Event();
	Eq[ne-1]->served = false;
	Eq[ne-1]->eV = p;
	Eq[ne-1]->type = INTERSECTION;
	Eq[ne-1]->intersectUpper = upper;
	Eq[ne-1]->intersectLower = lower;
	
	qsort( Eq, ne, sizeof(Event*), E_compare );

	ix = 0;

	#ifdef DEBUG
	for (int i=0; i < ne; i++) Eq[i]->eV->Print("event: ");
	#endif
	return true;
}

#endif
